package org.cybzacg.encryption.config;

import org.cybzacg.encryption.enums.EncryptionType;
import org.cybzacg.encryption.enums.EncryptionAlgorithm;
import org.cybzacg.encryption.enums.SecurityStrategyEnum;

import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import java.util.Properties;

/**
 * 加密配置类
 * 封装加密操作的所有配置参数
 * 
 * @author encryption team
 * @version 1.0
 */
public class EncryptionConfig {
    
    private final EncryptionType encryptionType;
    private final EncryptionAlgorithm algorithm;
    private final SecurityStrategyEnum securityStrategy;
    private final int keySize;
    private final String transformation;
    private final String provider;
    private final boolean cacheEnabled;
    private final long cacheExpiration;
    private final int maxCacheSize;
    private final boolean monitoringEnabled;
    private final long timeout;
    private final int maxRetries;
    private final long retryInterval;
    private final boolean batchMode;
    private final int batchSize;
    private final Map<String, Object> additionalProperties;
    
    private EncryptionConfig(Builder builder) {
        this.encryptionType = builder.encryptionType;
        this.algorithm = builder.algorithm;
        this.securityStrategy = builder.securityStrategy;
        this.keySize = builder.keySize;
        this.transformation = builder.transformation;
        this.provider = builder.provider;
        this.cacheEnabled = builder.cacheEnabled;
        this.cacheExpiration = builder.cacheExpiration;
        this.maxCacheSize = builder.maxCacheSize;
        this.monitoringEnabled = builder.monitoringEnabled;
        this.timeout = builder.timeout;
        this.maxRetries = builder.maxRetries;
        this.retryInterval = builder.retryInterval;
        this.batchMode = builder.batchMode;
        this.batchSize = builder.batchSize;
        this.additionalProperties = new HashMap<>(builder.additionalProperties);
    }
    
    /**
     * 获取加密类型
     * 
     * @return 加密类型
     */
    public EncryptionType getEncryptionType() {
        return encryptionType;
    }
    
    /**
     * 获取算法
     * 
     * @return 算法
     */
    public EncryptionAlgorithm getAlgorithm() {
        return algorithm;
    }
    
    /**
     * 获取安全策略
     * 
     * @return 安全策略
     */
    public SecurityStrategyEnum getSecurityStrategy() {
        return securityStrategy;
    }
    
    /**
     * 获取密钥长度
     * 
     * @return 密钥长度
     */
    public int getKeySize() {
        return keySize;
    }
    
    /**
     * 获取转换字符串
     * 
     * @return 转换字符串
     */
    public String getTransformation() {
        return transformation;
    }
    
    /**
     * 获取提供者
     * 
     * @return 提供者
     */
    public String getProvider() {
        return provider;
    }
    
    /**
     * 检查是否启用缓存
     * 
     * @return 是否启用缓存
     */
    public boolean isCacheEnabled() {
        return cacheEnabled;
    }
    
    /**
     * 获取缓存过期时间（毫秒）
     * 
     * @return 缓存过期时间
     */
    public long getCacheExpiration() {
        return cacheExpiration;
    }
    
    /**
     * 获取最大缓存大小
     * 
     * @return 最大缓存大小
     */
    public int getMaxCacheSize() {
        return maxCacheSize;
    }
    
    /**
     * 检查是否启用监控
     * 
     * @return 是否启用监控
     */
    public boolean isMonitoringEnabled() {
        return monitoringEnabled;
    }
    
    /**
     * 获取超时时间（毫秒）
     * 
     * @return 超时时间
     */
    public long getTimeout() {
        return timeout;
    }
    
    /**
     * 获取最大重试次数
     * 
     * @return 最大重试次数
     */
    public int getMaxRetries() {
        return maxRetries;
    }
    
    /**
     * 获取重试间隔（毫秒）
     * 
     * @return 重试间隔
     */
    public long getRetryInterval() {
        return retryInterval;
    }
    
    /**
     * 检查是否为批处理模式
     * 
     * @return 是否为批处理模式
     */
    public boolean isBatchMode() {
        return batchMode;
    }
    
    /**
     * 获取批次大小
     * 
     * @return 批次大小
     */
    public int getBatchSize() {
        return batchSize;
    }
    
    /**
     * 获取附加属性
     * 
     * @return 附加属性映射的副本
     */
    public Map<String, Object> getAdditionalProperties() {
        return new HashMap<>(additionalProperties);
    }
    
    /**
     * 获取附加属性值
     * 
     * @param key 键
     * @return 值，可能为null
     */
    public Object getAdditionalProperty(String key) {
        return additionalProperties.get(key);
    }
    
    /**
     * 创建建造者
     * 
     * @return 建造者实例
     */
    public static Builder builder() {
        return new Builder();
    }
    
    /**
     * 创建默认配置
     * 
     * @return 默认配置
     */
    public static EncryptionConfig createDefault() {
        return new Builder()
                .encryptionType(EncryptionType.SYMMETRIC)
                .algorithm(EncryptionAlgorithm.AES)
                .securityStrategy(SecurityStrategyEnum.SAFE)
                .keySize(256)
                .cacheEnabled(true)
                .cacheExpiration(300000) // 5分钟
                .maxCacheSize(1000)
                .monitoringEnabled(true)
                .timeout(15000) // 15秒
                .batchMode(false)
                .batchSize(100)
                .build();
    }
    
    /**
     * 从Properties创建配置
     * 
     * @param properties 属性
     * @return 配置
     */
    public static EncryptionConfig fromProperties(Properties properties) {
        Builder builder = new Builder();
        
        String encryptionType = properties.getProperty("encryption.type", "SYMMETRIC");
        builder.encryptionType(EncryptionType.fromName(encryptionType));
        
        String algorithm = properties.getProperty("encryption.algorithm", "AES");
        builder.algorithm(EncryptionAlgorithm.fromName(algorithm));
        
        String securityStrategy = properties.getProperty("encryption.strategy", "SAFE");
        builder.securityStrategy(SecurityStrategyEnum.fromName(securityStrategy));
        
        builder.keySize(Integer.parseInt(properties.getProperty("encryption.keySize", "256")));
        builder.transformation(properties.getProperty("encryption.transformation"));
        builder.provider(properties.getProperty("encryption.provider"));
        
        builder.cacheEnabled(Boolean.parseBoolean(properties.getProperty("encryption.cache.enabled", "true")));
        builder.cacheExpiration(Long.parseLong(properties.getProperty("encryption.cache.expiration", "300000")));
        builder.maxCacheSize(Integer.parseInt(properties.getProperty("encryption.cache.maxSize", "1000")));
        
        builder.monitoringEnabled(Boolean.parseBoolean(properties.getProperty("encryption.monitoring.enabled", "true")));
        builder.timeout(Long.parseLong(properties.getProperty("encryption.timeout", "15000")));
        builder.maxRetries(Integer.parseInt(properties.getProperty("encryption.maxRetries", "3")));
        builder.retryInterval(Long.parseLong(properties.getProperty("encryption.retryInterval", "1000")));
        
        builder.batchMode(Boolean.parseBoolean(properties.getProperty("encryption.batch.enabled", "false")));
        builder.batchSize(Integer.parseInt(properties.getProperty("encryption.batch.size", "100")));
        
        return builder.build();
    }
    
    /**
     * 建造者类
     */
    public static class Builder {
        private EncryptionType encryptionType = EncryptionType.SYMMETRIC;
        private EncryptionAlgorithm algorithm = EncryptionAlgorithm.AES;
        private SecurityStrategyEnum securityStrategy = SecurityStrategyEnum.SAFE;
        private int keySize = 256;
        private String transformation;
        private String provider;
        private boolean cacheEnabled = true;
        private long cacheExpiration = 300000; // 5分钟
        private int maxCacheSize = 1000;
        private boolean monitoringEnabled = true;
        private long timeout = 15000; // 15秒
        private int maxRetries = 3;
        private long retryInterval = 1000; // 1秒
        private boolean batchMode = false;
        private int batchSize = 100;
        private Map<String, Object> additionalProperties = new HashMap<>();
        
        public Builder encryptionType(EncryptionType encryptionType) {
            this.encryptionType = encryptionType;
            return this;
        }
        
        public Builder algorithm(EncryptionAlgorithm algorithm) {
            this.algorithm = algorithm;
            return this;
        }
        
        public Builder securityStrategy(SecurityStrategyEnum securityStrategy) {
            this.securityStrategy = securityStrategy;
            return this;
        }
        
        public Builder keySize(int keySize) {
            this.keySize = keySize;
            return this;
        }
        
        public Builder transformation(String transformation) {
            this.transformation = transformation;
            return this;
        }
        
        public Builder provider(String provider) {
            this.provider = provider;
            return this;
        }
        
        public Builder cacheEnabled(boolean cacheEnabled) {
            this.cacheEnabled = cacheEnabled;
            return this;
        }
        
        public Builder cacheExpiration(long cacheExpiration) {
            this.cacheExpiration = cacheExpiration;
            return this;
        }
        
        public Builder maxCacheSize(int maxCacheSize) {
            this.maxCacheSize = maxCacheSize;
            return this;
        }
        
        public Builder monitoringEnabled(boolean monitoringEnabled) {
            this.monitoringEnabled = monitoringEnabled;
            return this;
        }
        
        public Builder timeout(long timeout) {
            this.timeout = timeout;
            return this;
        }
        
        public Builder maxRetries(int maxRetries) {
            this.maxRetries = maxRetries;
            return this;
        }
        
        public Builder retryInterval(long retryInterval) {
            this.retryInterval = retryInterval;
            return this;
        }
        
        public Builder batchMode(boolean batchMode) {
            this.batchMode = batchMode;
            return this;
        }
        
        public Builder batchSize(int batchSize) {
            this.batchSize = batchSize;
            return this;
        }
        
        public Builder additionalProperty(String key, Object value) {
            this.additionalProperties.put(key, value);
            return this;
        }
        
        public Builder additionalProperties(Map<String, Object> additionalProperties) {
            this.additionalProperties = new HashMap<>(additionalProperties);
            return this;
        }
        
        public EncryptionConfig build() {
            return new EncryptionConfig(this);
        }
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EncryptionConfig that = (EncryptionConfig) o;
        return keySize == that.keySize &&
                cacheEnabled == that.cacheEnabled &&
                cacheExpiration == that.cacheExpiration &&
                maxCacheSize == that.maxCacheSize &&
                monitoringEnabled == that.monitoringEnabled &&
                timeout == that.timeout &&
                maxRetries == that.maxRetries &&
                retryInterval == that.retryInterval &&
                batchMode == that.batchMode &&
                batchSize == that.batchSize &&
                encryptionType == that.encryptionType &&
                algorithm == that.algorithm &&
                securityStrategy == that.securityStrategy &&
                Objects.equals(transformation, that.transformation) &&
                Objects.equals(provider, that.provider) &&
                Objects.equals(additionalProperties, that.additionalProperties);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(encryptionType, algorithm, securityStrategy, keySize, 
                          transformation, provider, cacheEnabled, cacheExpiration, 
                          maxCacheSize, monitoringEnabled, timeout, maxRetries, 
                          retryInterval, batchMode, batchSize, additionalProperties);
    }
    
    @Override
    public String toString() {
        return "EncryptionConfig{" +
                "encryptionType=" + encryptionType +
                ", algorithm=" + algorithm +
                ", securityStrategy=" + securityStrategy +
                ", keySize=" + keySize +
                ", cacheEnabled=" + cacheEnabled +
                ", monitoringEnabled=" + monitoringEnabled +
                ", timeout=" + timeout +
                ", batchMode=" + batchMode +
                '}';
    }
}
